#include <iostream>
using namespace std;
// g++ -o test_const test_const.cc -std=c++11
class A {
 public:
  A(int x = 10, int y = 20)
      : a(x),
        b(y) {
  }  // 没有这一行编译报错，因为成员变量a是一个常量，之后的值不可更改，必须进行初始化
  void Print1() { cout << a << " " << b << endl; }
  void Print2() const { cout << "const:" << a << " " << b << endl; }
  const int a = 0;
  int b;
};
void test_const_class() {
  A a1;
  const A a2;  // 常对象，内部隐含指针为const this
  a1.Print1();
  a1.Print2();  // 非常对象，常函数、非常函数都能调用，this能隐式转换为const
                // this
  // a2.Print1();  // 编译错误，常对象只能调用常函数
  return;
}

void test_const_ptr() {
  int var = 0;
  int* const a = &var;  // 指针常量，顶层const，指针不可更改
  const int* b;  // 常量指针，底层const，指针指向的值不可更改
  int c = 10;
  // a = &c;  // 编译错误，a是一个指针常量，即a指针为一个常量，不可更改
  b = &c;
  // *b = 10;  // 编译错误，b是一个常量指针，即b这个指针指向一个常量
}

void test_const_func(const A& a) {  // 为了提高效率和安全性
  // a.b = 100;  // 编译错误，不能修改a对象的值
  // const int var;  // 编译错误，常量必须初始化
  const int var = 999;
  cout << var << endl;
  return;
}

// C++中的const 不会从内存里读值,而是进行编译期的值替换
void test_const_keng() {
  // 编译期实际上是把10直接给了temp，这里的const就相当于编译期的#define
  int c = 10;
  const int temp = c;
  cout << temp << endl;  // 10
  c = 100;
  cout << temp << endl;  // 10

  const int n = 10;
  int* p = (int*)&n;  // 必须强制类型转换
  *p = 99;            // 修改const变量的值
  printf("%d\n", n);  // 10
}

int main() {
  // test_const_class();
  // test_const_ptr();
  // A a;
  // test_const_func(a);
  test_const_keng();
  return 0;
}